<?php
/**
 * 硬件指纹生成类
 */

namespace LicenseSDK\Hardware;

class MachineCode
{
    /**
     * 生成机器码
     * 
     * @return string
     */
    public static function generate()
    {
        $components = [];
        
        // 获取CPU信息
        $cpu = self::getCPUInfo();
        if ($cpu) {
            $components[] = 'CPU:' . $cpu;
        }
        
        // 获取硬盘序列号
        $disk = self::getDiskSerial();
        if ($disk) {
            $components[] = 'DISK:' . $disk;
        }
        
        // 获取MAC地址
        $mac = self::getMacAddress();
        if ($mac) {
            $components[] = 'MAC:' . $mac;
        }
        
        // 获取主板序列号
        $motherboard = self::getMotherboardSerial();
        if ($motherboard) {
            $components[] = 'MB:' . $motherboard;
        }
        
        // 如果没有获取到任何信息，使用服务器名称
        if (empty($components)) {
            $components[] = 'HOST:' . gethostname();
        }
        
        // 组合并生成唯一指纹
        $fingerprint = implode('|', $components);
        return hash('sha256', $fingerprint);
    }
    
    /**
     * 获取CPU信息
     * 
     * @return string|null
     */
    private static function getCPUInfo()
    {
        if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
            // Windows系统
            $cpu = self::executeCommand('wmic cpu get ProcessorId');
            if ($cpu) {
                $lines = explode("\n", $cpu);
                if (isset($lines[1])) {
                    return trim($lines[1]);
                }
            }
        } else {
            // Linux系统
            if (file_exists('/proc/cpuinfo')) {
                $cpuinfo = file_get_contents('/proc/cpuinfo');
                if (preg_match('/Serial\s+:\s+(\w+)/', $cpuinfo, $matches)) {
                    return $matches[1];
                }
                if (preg_match('/processor\s+:\s+(\d+)/', $cpuinfo, $matches)) {
                    return 'PROC' . $matches[1];
                }
            }
        }
        
        return null;
    }
    
    /**
     * 获取硬盘序列号
     * 
     * @return string|null
     */
    private static function getDiskSerial()
    {
        if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
            // Windows系统
            $disk = self::executeCommand('wmic diskdrive get SerialNumber');
            if ($disk) {
                $lines = explode("\n", $disk);
                if (isset($lines[1])) {
                    return trim($lines[1]);
                }
            }
        } else {
            // Linux系统
            $disk = self::executeCommand('lsblk -d -o serial 2>/dev/null | tail -1');
            if ($disk) {
                return trim($disk);
            }
            
            // 尝试其他方法
            $disk = self::executeCommand('hdparm -i /dev/sda 2>/dev/null | grep SerialNo');
            if ($disk && preg_match('/SerialNo=(\S+)/', $disk, $matches)) {
                return $matches[1];
            }
        }
        
        return null;
    }
    
    /**
     * 获取MAC地址
     * 
     * @return string|null
     */
    private static function getMacAddress()
    {
        if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
            // Windows系统
            $output = self::executeCommand('getmac');
            if ($output && preg_match('/([0-9A-F]{2}[:-]){5}([0-9A-F]{2})/i', $output, $matches)) {
                return str_replace(['-', ':'], '', $matches[0]);
            }
        } else {
            // Linux系统
            $interfaces = ['eth0', 'ens33', 'enp0s3', 'en0'];
            
            foreach ($interfaces as $interface) {
                $output = self::executeCommand("cat /sys/class/net/{$interface}/address 2>/dev/null");
                if ($output) {
                    return str_replace(':', '', trim($output));
                }
            }
            
            // 尝试ifconfig
            $output = self::executeCommand('ifconfig 2>/dev/null | grep -o -E "([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2}"');
            if ($output) {
                $macs = explode("\n", trim($output));
                if (!empty($macs[0])) {
                    return str_replace(':', '', $macs[0]);
                }
            }
        }
        
        return null;
    }
    
    /**
     * 获取主板序列号
     * 
     * @return string|null
     */
    private static function getMotherboardSerial()
    {
        if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
            // Windows系统
            $output = self::executeCommand('wmic baseboard get SerialNumber');
            if ($output) {
                $lines = explode("\n", $output);
                if (isset($lines[1])) {
                    return trim($lines[1]);
                }
            }
        } else {
            // Linux系统
            $output = self::executeCommand('dmidecode -t 2 2>/dev/null | grep Serial');
            if ($output && preg_match('/Serial Number:\s*(.+)/', $output, $matches)) {
                return trim($matches[1]);
            }
            
            // 尝试读取文件
            if (file_exists('/sys/class/dmi/id/board_serial')) {
                $serial = file_get_contents('/sys/class/dmi/id/board_serial');
                if ($serial) {
                    return trim($serial);
                }
            }
        }
        
        return null;
    }
    
    /**
     * 执行系统命令
     * 
     * @param string $command
     * @return string|null
     */
    private static function executeCommand($command)
    {
        try {
            if (function_exists('exec')) {
                $output = [];
                $return = 0;
                @exec($command, $output, $return);
                if ($return === 0 && !empty($output)) {
                    return implode("\n", $output);
                }
            }
            
            if (function_exists('shell_exec')) {
                $output = @shell_exec($command);
                if ($output !== null) {
                    return $output;
                }
            }
        } catch (\Exception $e) {
            // 忽略错误
        }
        
        return null;
    }
    
    /**
     * 获取详细的硬件信息（调试用）
     * 
     * @return array
     */
    public static function getDetailInfo()
    {
        return [
            'cpu' => self::getCPUInfo(),
            'disk' => self::getDiskSerial(),
            'mac' => self::getMacAddress(),
            'motherboard' => self::getMotherboardSerial(),
            'hostname' => gethostname(),
            'os' => PHP_OS,
            'php_version' => PHP_VERSION,
        ];
    }
}

